/**
 * This class detects if any other replica is dead or alive
 * using ControlUDPClient
 */
package com.comp6231.coordinator;

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * @author Farzana Alam
 * 
 */
public class FailureDetector {

	/*
	 * replica list
	 * 
	 * Key: Replica Name; Value: [0] => Host Name; [1] => Data UDP Port; [2] =>
	 * Control UDP Port;
	 */
	static Hashtable<String, String[]> coordinatorReplicaList = new Hashtable<String, String[]>();

	private String myReplicaName;

	private long timeout = 3000;

	private int myReplicaID;

	public FailureDetector(String myReplicaName, int myReplicaID,
			Hashtable<String, String[]> replicaList) {
		this.myReplicaName = myReplicaName;
		coordinatorReplicaList = replicaList;
		this.myReplicaID = myReplicaID;
		startPinging();
		System.out.println("Failure detection for " + myReplicaName
				+ " is initiated!");
	}

	/**
	 * 
	 */
	private void startPinging() {

		// final String pingMessage = "Control," + "SourceToBeRemoved," + "NA,"
		// + "Alive," + "Are you alive?";
		final String pingMessage = "Are you alive?";
		Enumeration<String> keys = coordinatorReplicaList.keys();
		while (keys.hasMoreElements()) {
			final String key = keys.nextElement();

			if (key.equalsIgnoreCase(myReplicaName))
				continue;
			/*
			 * [0] => Host Name; [1] => UDP Port; [2] => Entity Name; [3] =>
			 * Response (eg. "I am alive!")
			 */
			String[] replicaDetails = coordinatorReplicaList.get(key);
			final String hostName = replicaDetails[0];
			final String UDPPort = replicaDetails[2];

			Thread t = new Thread() {
				@Override
				public void run() {
					while (true) {
						String replyMessage = "";
						replyMessage = new ControlUDPClient().sendPacket(
								hostName, UDPPort, pingMessage);

						if (replyMessage.equalsIgnoreCase("no response")) {
							FailureDetector.this.removeReplica(key);
							break;
						}
						try {
							Thread.sleep(timeout);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			};
			t.start();
		}
	}

	/**
	 * @param key
	 */
	protected void removeReplica(String key) {
		coordinatorReplicaList.remove(key);
		System.out.println("Removing replica from " + myReplicaName + ": "
				+ key);
		ElectionSubsystem.initiateElection(coordinatorReplicaList, myReplicaID);
	}
}
